package com.caiyi.financial.nirvana.sms.gateway.sgip.handler;

import com.caiyi.financial.nirvana.sms.entity.SmsReceiveMessage;
import com.caiyi.financial.nirvana.sms.enums.SmsMsgStatusEnum;
import com.caiyi.financial.nirvana.sms.gateway.sgip.SGIPClient;
import com.caiyi.financial.nirvana.sms.gateway.sgip.SGIPHeader;
import com.caiyi.financial.nirvana.sms.gateway.sgip.message.SGIPMessage;
import com.caiyi.financial.nirvana.sms.gateway.sgip.message.body.*;
import com.caiyi.financial.nirvana.sms.jedis.JedisKey;
import com.caiyi.financial.nirvana.sms.jedis.JedisService;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SGIPServerHandler extends SimpleChannelInboundHandler<SGIPMessage> {
    private static final Logger logger = LoggerFactory.getLogger(SGIPServerHandler.class);

    private SGIPClient client;

    public SGIPServerHandler(SGIPClient client) {
        this.client = client;
    }

    @Override
    public void channelRead0(ChannelHandlerContext ctx, SGIPMessage msg) {
        int commandId = msg.getCommandID();
        logger.info("SGIP server收到消息：" + commandId);
        switch (commandId) {
            case SGIPMessage.SGIP_BIND:
                handleBind(ctx, msg);
                break;
            case SGIPMessage.SGIP_DELIVER:
                handleDeliver(ctx, msg);
                break;
            case SGIPMessage.SGIP_REPORT:
                handleReport(ctx, msg);
                break;
            case SGIPMessage.SGIP_UNBIND:
                handleUnbind(ctx, msg);
                break;
            default:
                break;
        }

    }

    private void handleBind(ChannelHandlerContext ctx, SGIPMessage msg) {
        SGIPBind body = (SGIPBind) msg.getBody();
        String spId = body.getSpId();
        String password = body.getPassword();
        logger.info("sgip login account:" + spId + ", password:" + password);
        //回复resp
        SGIPMessage resp = new SGIPMessage();
        SGIPHeader header = new SGIPHeader();
        header.setCommandID(SGIPMessage.SGIP_BIND_RESP);
        header.setSpNodeNum(msg.getSpNodeNum());
        header.setTimestamp(msg.getTimestamp());
        header.setSequenceId(msg.getSequenceId());
        resp.setHeader(header);

        SGIPBindResp respBody = new SGIPBindResp();
        respBody.setStatus((byte) 0);
        resp.setBody(respBody);

        ctx.writeAndFlush(resp);
    }

    private void handleDeliver(ChannelHandlerContext ctx, SGIPMessage msg) {
        SGIPDeliver deliver = (SGIPDeliver) msg.getBody();
        logger.info("SGIPServerHandler handleDeliver：{}", deliver.toString());
        String accessNumber = deliver.getSpNumber();
        SmsReceiveMessage message = new SmsReceiveMessage();
        message.setAccessNumber(accessNumber);
        String gatewayAccessNumber = client.info.getAccessNumber();
        String account = "";
        if (accessNumber.startsWith(gatewayAccessNumber)) {
            String extend = accessNumber.substring(gatewayAccessNumber.length());
            account = JedisService.get(String.format(JedisKey.SMS_EXTEND_ACCOUNT, extend));
        }
        message.setAccount(account);
        message.setContent(deliver.getMessageContent());
        message.setMessageId(Long.toHexString(msg.getMessageId()));
        message.setPhone(deliver.getUserNumber());
        client.receiveMessage(message);
        responseDeliveryMessage(ctx, msg);
    }

    private void responseDeliveryMessage(ChannelHandlerContext ctx, SGIPMessage msg) {
        SGIPMessage message = new SGIPMessage();
        SGIPHeader header = new SGIPHeader();
        header.setCommandID(SGIPMessage.SGIP_DELIVER_RESP);
        header.setSpNodeNum(msg.getSpNodeNum());
        header.setTimestamp(msg.getTimestamp());
        header.setSequenceId(msg.getSequenceId());
        message.setHeader(header);

        SGIPReportResp resp = new SGIPReportResp();
        resp.setResult(0);
        message.setBody(resp);

        ctx.writeAndFlush(message);
    }

    private void handleReport(ChannelHandlerContext ctx, SGIPMessage msg) {
        SGIPReport report = (SGIPReport) msg.getBody();
        logger.info("SGIPServerHandler handleReport：{}", report.toString());
        String remoteMsgId = Long.toHexString(report.getRemoteMsgId());
        String messageId = JedisService.hget(JedisKey.SMS_REMOTE_ID_MESSAGE_ID, remoteMsgId);
        JedisService.hdel(JedisKey.SMS_REMOTE_ID_MESSAGE_ID, remoteMsgId);
        if (StringUtils.isBlank(messageId)) {
            logger.warn("LtGateway notifyStatus messageId is null phone : {}, remoteMsgId : {}", report.getUserNumber(), remoteMsgId);
        }
        int status = SmsMsgStatusEnum.SEND_SUCCESS.index;
        String result = "DELIVRD";
        if (report.getStat() != 0) {
            status = SmsMsgStatusEnum.SEND_FAIL.index;
            result = "SGIP:" + report.getErorCode();
        }
        client.receiveReport(status, messageId, result);
        responseReportMessage(ctx, msg);
    }

    private void responseReportMessage(ChannelHandlerContext ctx, SGIPMessage msg) {
        SGIPMessage message = new SGIPMessage();
        SGIPHeader header = new SGIPHeader();
        header.setCommandID(SGIPMessage.SGIP_REPORT_RESP);
        header.setSpNodeNum(msg.getSpNodeNum());
        header.setTimestamp(msg.getTimestamp());
        header.setSequenceId(msg.getSequenceId());
        message.setHeader(header);

        SGIPReportResp resp = new SGIPReportResp();
        resp.setResult(0);
        message.setBody(resp);

        ctx.writeAndFlush(message);
    }

    private void handleUnbind(ChannelHandlerContext ctx, SGIPMessage msg) {
        //回复resp
        SGIPMessage resp = new SGIPMessage();
        SGIPHeader header = new SGIPHeader();
        header.setCommandID(SGIPMessage.SGIP_UNBIND_RESP);
        header.setSpNodeNum(msg.getSpNodeNum());
        header.setTimestamp(msg.getTimestamp());
        header.setSequenceId(msg.getSequenceId());
        resp.setHeader(header);

        SGIPUnbindResp respBody = new SGIPUnbindResp();
        resp.setBody(respBody);

        ctx.writeAndFlush(resp).addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) {
                future.channel().close();
            }
        });
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        logger.error(cause.getMessage(), cause);
    }


}
